package com.wuzuqing.android.eightdiagrams.term;


import java.math.BigDecimal;

public class ShouXingUtil extends ShouXingConstant {

    public static int floor(double value) {
        return (int) Math.floor(value);
    }

    public static double nutationLon2(double t) {
        double a = -1.742 * t, t2 = t * t, dl = 0;
        for (int i = 0, j = NUT_B.length; i < j; i += 5) {
            dl += (NUT_B[i + 3] + a) * Math.sin(NUT_B[i] + NUT_B[i + 1] * t + NUT_B[i + 2] * t2);
            a = 0;
        }
        return dl / 100 / SECOND_PER_RAD;
    }

    public static double eLon(double t, int n) {
        t /= 10;
        double v = 0, tn = 1;
        int n1 = 0, n2 = 0;
        int m;
        double c;
        int pn = 1;
        double n0=0, m0 = XL0[pn + 1] - XL0[pn];

        for (int i = 0; i < 6; i++, tn *= t) {
            n1 = floor(XL0[pn + i]);
            n2 = floor(XL0[pn + 1 + i]);
            n0 = n2 - n1;
            if (n0 == 0) {
                continue;
            }
            if (n < 0) {
                m = n2;
            } else {
                m = floor((3 * n * n0 / m0 + 0.5) + n1);
                if (i != 0) {
                    m += 3;
                }
                if (m > n2) {
                    m = n2;
                }
            }
            c = 0;
            for (int j = n1; j < m; j += 3) {
                c += XL0[j] * Math.cos(XL0[j + 1] + t * XL0[j + 2]);
            }
            v += c * tn;
        }
        v /= XL0[0];
        double t2 = t * t;
        v += (-0.0728 - 2.7702 * t - 1.1019 * t2 - 0.0996 * t2 * t) / SECOND_PER_RAD;
        return v;
    }

    public static double mLon(double t, int n,String from) {
        double[][] ob = XL1;
        int obl = ob[0].length;
        double tn = 1;
        double v = 0;
        int j;
        double c;

        double t2 = t * t, t3 = t2 * t, t4 = t3 * t, t5 = t4 * t, tx = t - 10;
        v += (3.81034409 + 8399.684730072 * t - 3.319e-05 * t2 + 3.11e-08 * t3 - 2.033e-10 * t4) * SECOND_PER_RAD;
         v += 5028.792262 * t + 1.1124406 * t2 + 0.00007699 * t3 - 0.000023479 * t4 - 0.0000000178 * t5;
        if (tx > 0) {
            v += -0.866 + 1.43 * tx + 0.054 * tx * tx;
        }
        t2 /= 1e4;
        t3 /= 1e8;
        t4 /= 1e8;
        n *= 6;
        if (n < 0) {
            n = obl;
        }
//        System.out.println(from+" "+BigDecimal.valueOf(t)+" "+BigDecimal.valueOf(v)
//                +" "+BigDecimal.valueOf(t2)+" "+BigDecimal.valueOf(t3)+" "+BigDecimal.valueOf(t4)+" "+BigDecimal.valueOf(tx));
        for (int i = 0, x = ob.length; i < x; i++,
                tn *= t) {
            double[] f = ob[i];
            int l = f.length;
            int m = floor((n*1f * l / obl + 0.5));
            if (i > 0) {
                m += 6;
            }
            if (m >= l) {
                m = l;
            }
//            System.out.println(i+" "+m);
            for (j = 0,
                         c = 0; j < m; j += 6) {
                c += f[j] * Math.cos(f[j + 1] + t * f[j + 2] + t2 * f[j + 3] + t3 * f[j + 4] + t4 * f[j + 5]);
                //          console.log(i,m,j,c);
//                System.out.println(i+" "+m+" "+j+" "+BigDecimal.valueOf(f[j])+" "+BigDecimal.valueOf(c));
            }
            v += c * tn;
//            System.out.println(i+" "+m+" "+BigDecimal.valueOf(c)+" "+BigDecimal.valueOf(tn)+" "+BigDecimal.valueOf(v));
        }
//        System.out.println("------------------------------------");
        v /= SECOND_PER_RAD;
        return v;
    }


    public static double gxcSunLon(double t) {
        double t2 = t * t;
        double v = -0.043126 + 628.301955 * t - 0.000002732 * t2;
        double e = 0.016708634 - 0.000042037 * t - 0.0000001267 * t2;
        return -20.49552 * (1 + e * Math.cos(v)) / SECOND_PER_RAD;
    }

    public static double ev(double t) {
        double f = 628.307585 * t;
        return 628.332 + 21 * Math.sin(1.527 + f) + 0.44 * Math.sin(1.48 + f * 2) + 0.129 * Math.sin(5.82 + f) * t + 0.00055 * Math.sin(4.21 + f) * t * t;
    }

    public static double saLon(double t, int n) {
        return eLon(t, n) + nutationLon2(t) + gxcSunLon(t) + Math.PI;
    }

    public static double dtExt(double y, int jsd) {
        double dy = (y - 1820) / 100;
        return -20 + jsd * dy * dy;
    }

    public static double dtCalc(double y) {
        int size = DT_AT.length;
        double y0 = DT_AT[size - 2];
        double t0 = DT_AT[size - 1];
        if (y >= y0) {
            int jsd = 31;
            if (y > y0 + 100) {
                return dtExt(y, jsd);
            }
            return dtExt(y, jsd) - (dtExt((int) y0, jsd) - t0) * (y0 + 100 - y) / 100;
        }
        int i;
        for (i = 0; i < size; i += 5) {
            if (y < DT_AT[i + 5]) {
                break;
            }
        }
        double t1 = (y - DT_AT[i]) / (DT_AT[i + 5] - DT_AT[i]) * 10, t2 = t1 * t1, t3 = t2 * t1;
        return DT_AT[i + 1] + DT_AT[i + 2] * t1 + DT_AT[i + 3] * t2 + DT_AT[i + 4] * t3;
    }

    public static double dtT(double t) {
        return dtCalc( (t / 365.2425 + 2000)) / SECOND_PER_DAY;
    }

    public static double mv(double t) {
        double v = 8399.71 - 914 * Math.sin(0.7848 + 8328.691425 * t + 0.0001523 * t * t);
        v -= 179 * Math.sin(2.543 + 15542.7543 * t) + 160 * Math.sin(0.1874 + 7214.0629 * t) + 62 * Math.sin(3.14 + 16657.3828 * t) + 34 * Math.sin(4.827 + 16866.9323 * t) + 22 * Math.sin(4.9 + 23871.4457 * t) + 12 * Math.sin(2.59 + 14914.4523 * t) + 7 * Math.sin(0.23 + 6585.7609 * t) + 5 * Math.sin(0.9 + 25195.624 * t) + 5 * Math.sin(2.32 - 7700.3895 * t) + 5 * Math.sin(3.88 + 8956.9934 * t) + 5 * Math.sin(0.49 + 7771.3771 * t);
        return v;
    }

    public static double saLonT(double w) {
        double t, v = 628.3319653318;
        t = (w - 1.75347 - Math.PI) / v;
        v = ev(t);
        t += (w - saLon(t, 10)) / v;
        v = ev(t);
        t += (w - saLon(t, -1)) / v;
        return t;
    }

    public static double msaLon(double t, int mn, int sn) {
        return mLon(t, mn,"msaLon") + (-3.4E-6) - (eLon(t, sn) + gxcSunLon(t) + Math.PI);
    }

    public static double msaLonT(double w) {
        double t, v = 7771.37714500204;
        t = (w + 1.08472) / v;

        t += (w - msaLon(t, 3, 3)) / v;
//        System.out.println("msaLonT 1:"+BigDecimal.valueOf(t));
        v = mv(t) - ev(t);
        t += (w - msaLon(t, 20, 10)) / v;
//        System.out.println("msaLonT 2:"+BigDecimal.valueOf(t));
        t += (w - msaLon(t, -1, 60)) / v;
//        System.out.println("msaLonT 3:"+BigDecimal.valueOf(t));
        return t;
    }

    public static double msaLonT2(double w) {
        double t, v = 7771.37714500204;
        t = (w + 1.08472) / v;
//        System.out.println(2+" "+t);
        double l, t2 = t * t;
        t -= (-0.00003309 * t2 + 0.10976 * Math.cos(0.784758 + 8328.6914246 * t + 0.000152292 * t2) + 0.02224 * Math.cos(0.18740 + 7214.0628654 * t - 0.00021848 * t2) - 0.03342 * Math.cos(4.669257 + 628.307585 * t)) / v;

        t2 = t * t;
        l = mLon(t, 20,"msaLonT2") - (4.8950632 + 628.3319653318 * t + 0.000005297 * t2 + 0.0334166 * Math.cos(4.669257 + 628.307585 * t) +
                0.0002061 * Math.cos(2.67823 + 628.307585 * t) * t + 0.000349 * Math.cos(4.6261 + 1256.61517 * t) - 20.5 / SECOND_PER_RAD);
//        System.out.println(3+" "+ BigDecimal.valueOf(l));
        //  - (4.8950632 + 628.3319653318 * t + 0.000005297 * t2  )
        v = 7771.38 - 914 * Math.sin(0.7848 + 8328.691425 * t + 0.0001523 * t2) - 179 * Math.sin(2.543 + 15542.7543 * t) - 160 * Math.sin(0.1874 + 7214.0629 * t);
        t += (w - l) / v;
//        System.out.println(3+" "+w+" "+t);
        return t;
    }

    public static double shuoHigh(double w) {
        double t = msaLonT2(w) * 36525;
//        System.out.println(1+" "+w+" "+t);
//        System.out.println("shuoHigh "+BigDecimal.valueOf(t)+" "+BigDecimal.valueOf(w));
        t = t - dtT(t) + ONE_THIRD;
        double v = ((t + 0.5) % 1) * SECOND_PER_DAY;
//        System.out.println("shuoHigh "+BigDecimal.valueOf(t)+" "+BigDecimal.valueOf(v));
        if (v < 1800 || v > SECOND_PER_DAY - 1800) {
            t = msaLonT(w) * 36525 - dtT(t) + ONE_THIRD;
        }

        return t;
    }

    public static double shuoLow(double w) {
        double v = 7771.37714500204;
        double t = (w + 1.08472) / v;
        t -= (-0.0000331 * t * t + 0.10976 * Math.cos(0.785 + 8328.6914 * t) + 0.02224 * Math.cos(0.187 + 7214.0629 * t) - 0.03342 * Math.cos(4.669 + 628.3076 * t)) / v + (32 * (t + 1.8) * (t + 1.8) - 20) / SECOND_PER_DAY / 36525;
        return t * 36525 + ONE_THIRD;
    }

    public static void main(String[] args) {
        System.out.println(calcShuo(35413.0 + 29.5306 * 8));
    }

    public static double calcShuo(double jd) {

        int size = SHUO_KB.length;
        int d = 0;
        int pc = 14, i;
        jd += Solar.J2000;
        double f1 = SHUO_KB[0] - pc, f2 = SHUO_KB[size - 1] - pc, f3 = 2436935;
//        System.out.println("calcShuo"+jd+",size:"+size+",f1:"+f1+",f2:"+f2+",f3:"+f3);
        if (jd < f1 || jd >= f3) {

            //  d = Math.floor(this.shuoHigh(Math.floor((jd + pc - 2451551) / 29.5306) * Math.PI * 2) + 0.5);
            d = floor(shuoHigh(floor((jd + pc - 2451551) / 29.5306) * Math.PI * 2) + 0.5);
        } else if (jd >= f1 && jd < f2) {
            for (i = 0; i < size; i += 2) {
                if (jd + pc < SHUO_KB[i + 2]) {
                    break;
                }
            }
            d = (int) (SHUO_KB[i] + SHUO_KB[i + 1] * floor((jd + pc - SHUO_KB[i]) / SHUO_KB[i + 1]));
            d = floor(d + 0.5);
            if (d == 1683460) {
                d++;
            }
            d -= Solar.J2000;
//            System.out.println(2+" "+d);
        } else if (jd >= f2 && jd < f3) {
            d = floor(shuoLow(Math.floor((jd + pc - 2451551) / 29.5306) * Math.PI * 2) + 0.5);

            int from = floor((jd - f2) / 29.5306);
            int n = Integer.parseInt(SB.substring(from, from+1));
            if (1 == n) {
                d += 1;
            } else if (2 == n) {
                d -= 1;
            }
//            System.out.println(3+" "+d);
        }
        return d;
    }
}
